#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/system.h>

#define set_bit(bitnr,addr) ({ \
register int __res ; \
__asm__("bt %2, %3\n\tsetb %%al":"=a"(__res): "a"(0), "r"(bitnr), "m"(*(addr))); \
__res; })

struct super_block super_block[NR_SUPER];

int ROOT_DEV = 0;

struct super_block *get_super(int dev)
{
    struct super_block *s;

    if (!dev)
        return NULL;
    s = super_block;
    while (s < NR_SUPER + super_block)
        if (s->s_dev == dev)
            return s;
        else
            s++;
    return NULL;
}

static struct super_block *read_super(int dev)
{
    struct super_block *s;
    struct buffer_head *bh;
    int i, block;

    if (!dev)
        return NULL;
    
    s = get_super(dev);
    if (s)  // 如果超级块信息已经被读入内存
        return s;
    for (s = super_block; ; s++) {
        if (s >= NR_SUPER + super_block)
            return NULL;    // 如果没有空闲的超级块结构体
        if (!s->s_dev)
            break;
    }
    s->s_dev = dev;
    bh = bread(dev, 1);
    if (!bh) {
        s->s_dev = 0;
        return NULL;
    }
    __asm__("cld"::);   // 不加这句，结构体赋值会出错
    *(struct d_super_block *)s = *((struct d_super_block *)bh->b_data);
    brelse(bh);
    if (s->s_magic != SUPER_MAGIC) {    // 如果超级块的数据有问题
        s->s_dev = 0;
        return NULL;
    }
    for (i = 0; i < I_MAP_SLOTS; i++)
        s->s_imap[i] = NULL;
    for (i = 0; i < Z_MAP_SLOTS; i++)
        s->s_zmap[i] = NULL;
    block = 2;  // 2号逻辑块是inode位图
    for (i = 0; i < s->s_imap_blocks; i++) {   // 读取inode位图
        s->s_imap[i] = bread(dev, block);
        if (s->s_imap[i])
            block++;
        else
            break;
    }
    for (i = 0; i < s->s_zmap_blocks; i++) {    // 读取逻辑块位图
        s->s_zmap[i] = bread(dev, block);
        if (s->s_zmap[i])
            block++;
        else
            break;
    }
    if (block != 2 + s->s_imap_blocks + s->s_zmap_blocks) {
        // 如果读取的数量出现问题，将读取的数据释放掉
        for(i = 0; i < I_MAP_SLOTS; i++)
            brelse(s->s_imap[i]);
        for(i = 0; i < Z_MAP_SLOTS; i++)
            brelse(s->s_zmap[i]);
        s->s_dev = 0;
        return NULL;
    }
    s->s_imap[0]->b_data[0] |= 1;   // 修改inode位图，表示该节点已被使用
    s->s_zmap[0]->b_data[0] |= 1;   // 修改逻辑块位图，表示该逻辑块已被使用
    return s;
}

void mount_root(void)
{
    int i, free;
    struct super_block *p;
    struct m_inode *mi;
    
    p = read_super(ROOT_DEV);
    if (!p)
        panic("Unable to mount root");
    mi = iget(ROOT_DEV, ROOT_INO);
    if (!mi)
        panic("Unable to read root i-node");
    mi->i_count += 1;
    current->pwd = mi;
    current->root = mi;
    free = 0;
    i = p->s_nzones;        // 逻辑块数
    while (--i >= 0)
        if (!set_bit(i & 8191, p->s_zmap[i >> 13]->b_data))
            free++;
    printk("%d/%d free blocks\n", free, p->s_nzones);
    free = 0;
    i = p->s_ninodes + 1;   // inode数
    while (--i >= 0)
        if (!set_bit(i & 8191, p->s_imap[i >> 13]->b_data))
            free++;
    printk("%d/%d free inodes\n", free, p->s_ninodes);
}